import SocketClient from '@/api/socket.js'
import {
	socketApiUrl
} from '@/api/base.js'
import request from '@/api/request.js'
// 1、导演负责完成网络通信初始化，接受网络数据，然后执行外部的回调函数，并携带参数data返回给被调用者
// 2、导演负责指定先后手
// 3、控制选手方是否可执行下棋
// 4、边界判断，并修改棋面的所有class属性，显示页面
class Director {
	constructor(chessList, area_id, onReceive, onErrorEvent, onErrorSucceed, successCallback) {
		this.area_id = area_id
		this.chessList = chessList
		this.onReceive = onReceive;
		this.onErrorEvent = onErrorEvent
		this.onErrorSucceed = onErrorSucceed
		this.successCallback = successCallback
		this.isConnected = this.connect(this.area_id)
		this.initVoice()
	}

	connect(area_id) {
		if (!this.socket && this.area_id) {
			let connectURL = socketApiUrl + this.area_id
			this.socket = new SocketClient(connectURL, this.onReceive, this.onErrorEvent, this
				.onErrorSucceed,
				this.area_id)
		}
	}
	close() {
		if (this.socket) {
			this.socket.stop();
			this.socket = null;
			console.log("关闭socket连接")
		}
	}
	fillChessList(chessList) {
		this.chessList = chessList
	}
	// 初始化棋盘棋子
	initChess() {
		for (var i = 0; i < 3; i++) {
			for (var j = 0; j < 3; j++) {
				if (j == 0) {
					this.chessList.push({
						x: j,
						y: i,
						classname: `box_${j}_${i} white_chess`,
						hand: "white"
					})
				}

				if (j == 1) {
					this.chessList.push({
						x: j,
						y: i,
						classname: `box_${j}_${i} empty_chess`,
						hand: "empty"
					})
				}

				if (j == 2) {
					this.chessList.push({
						x: j,
						y: i,
						classname: `box_${j}_${i} black_chess`,
						hand: "black"
					})
				}

			}
		}
		return {
			action: "init",
			data: this.chessList
		}
	}
	//与服务器发送网络请求，POST
	async sendMsg(user_id) {
		await request.post('chess/msg', {
			user_id: user_id,
			group_id: this.group_id,
			chessList: this.chessList
		})
	}
	//宣布胜利
	declare(winPart) {
		console.log(`${winPart}胜利`)
		this.successCallback(winPart)
	}

	getData() {
		return this.data
	}
	getChessList() {
		return this.chessList
	}

	// 指定先手后手
	appoint() {
		let hand = Math.random() > 0.5 ? true : false;
		if (hand) {
			return 'black'
		} else {
			return 'white'
		}
	}
	getHoldChess() {
		return this.holdChess;
	}
	setHoldChess(chess) {
		this.holdChess = chess
	}


	setActiveStyle(node) {
		console.log("setActiveStyle")
		let index = this.chessList.findIndex(n => n.x == node.x && n.y == node.y)
		this.chessList[index].classname += ` active`
		return this.chessList
	}

	clearActiveStyle() {
		console.log("clearActiveStyle")
		let newList = this.chessList.map(item => {
			let newClass = item.classname.replace("active", "")
			return {
				x: item.x,
				y: item.y,
				classname: newClass,
				hand: item.hand
			}
		})
		this.chessList = newList
	}
	removeActiveStyle(node) {
		let index = this.chessList.findIndex(n => n.x == node.x && n.y == node.y)
		if (index == -1) {
			console.error("未找到需要移除的样式")
		}
		this.chessList[index].classname.replace('active', '')
		return this.chessList
	}
	// 交换棋子,source为holdChess
	exchange(source, target) {


		let sindex = this.chessList.findIndex(item => item.x == source.x && item.y == source.y)
		let sourceChess = this.chessList[sindex]

		let tindex = this.chessList.findIndex(item => item.x == target.x && item.y == target.y)

		let targetChess = this.chessList[tindex]

		// 1、判断是否为相同的节点
		const isSame = this.isSameNode(sourceChess, targetChess)

		// 2、相同的棋子
		if (isSame) {
			uni.showToast({
				icon: 'none',
				title: "选中相同棋子"
			})
			return {
				action: "sameChess",
				data: this.chessList
			}
		}


		// 3、同方棋子
		if (this.isSameSide(sourceChess, targetChess)) {
			this.postHoldVoice()

			//执行同节点交换
			this.chessList[sindex] = {
				x: sourceChess.x,
				y: sourceChess.y,
				hand: targetChess.hand,
				classname: sourceChess.classname.replace('active', "")
			}

			this.chessList[tindex] = {
				x: targetChess.x,
				y: targetChess.y,
				hand: targetChess.hand,
				classname: sourceChess.classname.includes('active') ? sourceChess.classname : sourceChess
					.classname += ` active`
			}
			this.setHoldChess(this.chessList[tindex])
			return {
				action: "sameSide",
				data: this.chessList
			}
		}

		// 对方棋子
		if (targetChess.hand !== sourceChess.hand && targetChess.hand !== "empty") {
			//说明是对方棋子
			this.postStopVoice()
			uni.showToast({
				icon: 'none',
				title: "无法操作对方棋子"
			})
			return {
				action: "againstChess",
				data: this.chessList
			}
		}
		// 2、目标棋子必须可以是空棋子，但不允许是对方棋子
		// 2-1、当是同方棋子时，执行改动走棋的棋子，不判断位置，不执行交换
		//2-2-2、判断边界
		if (this.checkBottom(sourceChess, targetChess)) {
			uni.showToast({
				icon: 'none',
				title: "底部棋子不能左右移动"
			})
			return {
				action: "bottomChess",
				data: this.chessList
			}
		}

		//2-3、如果是空棋子，判断边界，同时判断游戏规则
		if (targetChess.hand == "empty") {

			//2-3-1、是否相邻
			if (!this.isNeighborNode(sourceChess, targetChess)) {
				this.postHoldVoice()
				uni.showToast({
					icon: "none",
					title: "无法移动"
				})
				return this.chessList
			}
			// 2-3-1、底边棋子无法相互移动
			if (sourceChess.y == 2 && targetChess.y == 2) {
				uni.showToast({
					icon: "none",
					title: "底部棋子无法横向移动"
				})
				return {
					action: "bottomChess",
					data: this.chessList
				}
			}
			// 2-3-3、执行最终交换

			let holdChess = this.getHoldChess()
			this.chessList[sindex] = {
				x: sourceChess.x,
				y: sourceChess.y,
				hand: "empty",
				classname: `box_${sourceChess.x}_${sourceChess.y} empty_chess`
			}

			let newTargetChess = {
				x: targetChess.x,
				y: targetChess.y,
				classname: `box_${targetChess.x}_${targetChess.y} ${sourceChess.hand}_chess`,
				hand: sourceChess.hand
			}

			this.chessList[tindex] = newTargetChess
			//执行移动
			this.setHoldChess(newTargetChess)
			// 选手无移动条件，同时所有棋子的y坐标全为2时
			if (this.canMove(this.holdChess.hand)) {
				if (this.isWin(this.holdChess.hand)) {
					// 宣布获胜方
					this.declare(this.holdChess.hand)
					return {
						action: "gameover",
						data: this.chessList
					}
				} else {
					//执行让其操作。
					this.giveaway(this.holdChess.hand)
					return {
						action: "giveaway",
						data: this.chessList
					}
				}
			}
			// console.log(this.chessList)

			this.postPlayingVoice()
			return {
				action: "done",
				data: this.chessList
			}
		}

		return {
			action: "done",
			data: this.chessList
		}
	}
	//hand方是否输掉比赛
	isWin(hand) {
		let currHandChessList = this.chessList.filter(item => item.hand == this.holdChess.hand)
		let againstHand = hand == "black" ? "white" : "black";

		let againstHandChessList = this.chessList.filter(item => item.hand == againstHand)
		if (currHandChessList.every(item => item.y == 1) && againstHandChessList.every(item => item.y == 2)) {
			return true
		} else {
			return false
		}
	}
	// 让棋
	giveaway(hand) {
		// 当对方已经无路可走的时候，判断对方棋子是否全在牢（三个棋子的y:2）中，如果在牢中，需要我方让棋，腾出空位，
		console.log(`${hand}让棋`)
	}

	isSameNode(node1, node2) {
		if (node1.x == node2.x && node1.y == node2.y) {
			return true;
		}
		return false;
	}

	//同一方棋子
	isSameSide(node1, node2) {
		if (node1.hand == node2.hand) {
			return true;
		} else {
			return false;
		}
	}

	initVoice() {

		this.holdVoiceCtx = uni.createInnerAudioContext();
		this.holdVoiceCtx.autoplay = false;
		this.holdVoiceCtx.loop = false;
		this.holdVoiceCtx.src = 'https://xiaohongpao.top/music/hold.mp3';

		this.playingVoiceCtx = uni.createInnerAudioContext();
		this.playingVoiceCtx.autoplay = false;
		this.playingVoiceCtx.loop = false;
		this.playingVoiceCtx.src = 'https://xiaohongpao.top/music/down.mp3';

		this.playingVictoryCtx = uni.createInnerAudioContext();
		this.playingVictoryCtx.autoplay = false;
		this.playingVictoryCtx.loop = false;
		this.playingVictoryCtx.src = 'https://xiaohongpao.top/music/victory.mp3';

		this.playingFailtureCtx = uni.createInnerAudioContext();
		this.playingFailtureCtx.autoplay = false;
		this.playingFailtureCtx.loop = false;
		this.playingFailtureCtx.src = 'https://xiaohongpao.top/music/failture.mp3';

		this.playingStoptureCtx = uni.createInnerAudioContext();
		this.playingStoptureCtx.autoplay = false;
		this.playingStoptureCtx.loop = false;
		this.playingStoptureCtx.src = 'https://xiaohongpao.top/music/failture.mp3';
	}

	postHoldVoice() {
		this.holdVoiceCtx.play()
	}

	postPlayingVoice() {
		this.playingVoiceCtx.play()
	}

	postFailtureVoice() {
		this.playingFailtureCtx.play()
	}

	postVictoryVoice() {
		this.playingVictoryCtx.play()
	}

	postStopVoice() {
		this.playingStoptureCtx.play()
	}
	// 是否相邻
	isNeighborNode(node1, node2) {

		let subNode = this.subNode(node1, node2);
		if (subNode.x == 1 && subNode.y == 0) {
			return true;
		}
		if (subNode.x == -1 && subNode.y == 0) {
			return true;
		}
		if (subNode.x == 0 && subNode.y == 1) {
			return true;
		}
		if (subNode.x == 0 && subNode.y == -1) {
			return true;
		}
		return false;
	}

	//节点相减
	subNode(node1, node2) {
		return {
			x: node1.x - node2.x,
			y: node1.y - node2.y
		}
	}



	//检测是否在底部，同时进行了左右移动
	checkBottom(source, target) {
		if (source.y == 2 && target.y == 2) {
			return true
		}
		return false
	}

	// 判断是否获胜,hand为下棋方
	canMove(hand) {

		// 1、通过空棋子进行判断
		// 2、附加条件，判断的棋子中如果y=2,即便是空棋子与之相邻，也不算是可下一步走子。
		// 3、下棋后，判断对方是否无路可走，如果为真，我方胜利。

		// 获取空棋子
		let emptyArr = this.chessList.filter(item => item.hand == "empty")
		// 获取对手方
		let againstHand = hand == "black" ? "white" : "black"

		//对手方棋子
		let againstArr = this.chessList.filter(item => item.hand == againstHand)

		// roads为可下一步走棋的数组
		let roads = []
		emptyArr.map(e => {
			againstArr.map(a => {
				if (e.y == 2 && a.y == 2) {
					roads.push(0)
				} else {
					if (this.isNeighborNode(e, a)) {
						roads.push(1)
					} else {
						roads.push(0)
					}
				}
			})
		})
		// console.log("roads为可下一步走棋的数组",roads)
		let roadsNum = roads.reduce((pre, curr) => pre + curr)

		if (roadsNum == 0) {
			return true;
		} else {
			return false;
		}

	}

}

export default Director